package guida.ccf.gzuexaminesystem.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import guida.ccf.gzuexaminesystem.common.HttpStatus;
import guida.ccf.gzuexaminesystem.common.HttpStatusDescriptions;
import guida.ccf.gzuexaminesystem.common.ResponseResult;
import guida.ccf.gzuexaminesystem.dto.LoginDto;
import guida.ccf.gzuexaminesystem.entity.Admin;
import guida.ccf.gzuexaminesystem.entity.StudentInfo;
import guida.ccf.gzuexaminesystem.exception.CustomLoginException;
import guida.ccf.gzuexaminesystem.mapper.StudentInfoMapper;
import guida.ccf.gzuexaminesystem.redis.RedisCache;
import guida.ccf.gzuexaminesystem.security.LoginAdmin;
import guida.ccf.gzuexaminesystem.security.LoginStudentInfo;
import guida.ccf.gzuexaminesystem.service.StudentInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import guida.ccf.gzuexaminesystem.utils.JwtUtil;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ccf
 * @since 2023-11-03
 */
@Service
public class StudentInfoServiceImpl extends ServiceImpl<StudentInfoMapper, StudentInfo> implements StudentInfoService {

    @Autowired
    private AuthenticationManager authentication;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private HttpStatusDescriptions descriptions;



    /**
     * 用户登录接口
     * @param user 实体类
     * @return 返回结果
     */
    @Override
    public ResponseResult<?> login(LoginDto user) {

        // 获取 AuthenticationManager 的 authenticate 方法进行认证
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate = authentication.authenticate(authenticationToken);

        if (Objects.isNull(authenticate)) {
            // 认证不通过
            throw new RuntimeException("登录失败!");
        }
        // 认证通过, 生成 jwt, 否则直接返回
        // 获取用户对象
        LoginStudentInfo loginUser = (LoginStudentInfo) authenticate.getPrincipal();

        // 生成 jwt
        StudentInfo studentInfo = loginUser.getUser();
        String roleType = studentInfo.getRoleType();
        String studentId = studentInfo.getStudentId();
        HashMap<String , Object> map = new HashMap<>();
        map.put("roleType", roleType);
        map.put("userId", studentId);

        String token = JwtUtil.createJWT(map, user.getJwtId());

        // 将 token 存入 redis
        loginUser.setJwtId(user.getJwtId());
        redisCache.setCacheObject(roleType + "-" + studentId, loginUser);

        HashMap<String, Object> result = new HashMap<>();
        result.put("userId", studentId);
        result.put("token", token);
        result.put("username", studentInfo.getName());
        return ResponseResult.success(result);
    }

    /**
     *  用户退出登录接口
     * @return 返回结果
     */
    @Override
    public ResponseResult<?> logout() {
        // 1. SecurityContextHolder 中的用户对象
        UsernamePasswordAuthenticationToken authenticationToken =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginAdmin loginUser = (LoginAdmin) authenticationToken.getPrincipal();
        if (Objects.isNull(loginUser)) {
            throw new CustomLoginException();
        }
        Admin admin = loginUser.getUser();

        // 2. 获取用户id 和 roleType
        String userId = admin.getId().toString();
        String roleType = admin.getRoleType();

        // 3. 删除 redis 中的值
        redisCache.deleteObject(roleType + "-" + userId);

        return ResponseResult.success(descriptions.getDescription(HttpStatus.OK));
    }

    /**
     * 通过学号查姓名
     */
    @Override
    public String selectNameByStudentId(String studentId) {
        LambdaQueryWrapper<StudentInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StudentInfo::getStudentId, studentId);
        StudentInfo studentInfo = getOne(lambdaQueryWrapper);
        if (studentId == null) {
            return "学号错误";
        }

        return studentInfo.getName();
    }


}
